"""
提示词链（Prompt Chaining）演示
====================================

核心概念：
1. 将复杂任务分解为多个简单步骤
2. 每一步的输出作为下一步的输入
3. 逐步构建最终解决方案

本示例演示：
- 场景：产品评论分析系统
- 步骤1：提取评论中的关键信息
- 步骤2：分析情感和问题点
- 步骤3：生成改进建议

参考：https://adp.xindoo.xyz/chapters/Chapter%201_%20Prompt%20Chaining/
"""

import json
from typing import Dict, Any


# ============================================
# 模拟 LLM 调用（实际应用中替换为真实 API）
# ============================================

def simulate_llm_call(prompt: str, context: str = "") -> str:
    """
    模拟 LLM 调用
    在实际应用中，这里应该调用 OpenAI、Claude 等 API
    """
    # 这里用简单的规则来模拟不同步骤的响应
    if "提取关键信息" in prompt:
        return json.dumps({
            "产品类型": "无线耳机",
            "优点": ["音质清晰", "佩戴舒适", "续航持久"],
            "缺点": ["连接不稳定", "价格偏高"],
            "用户需求": "通勤使用，需要稳定连接"
        }, ensure_ascii=False, indent=2)
    
    elif "分析情感" in prompt:
        return json.dumps({
            "整体情感": "中性偏正面",
            "满意度评分": 7,
            "主要问题": "连接稳定性影响用户体验",
            "关键痛点": "在地铁等复杂环境下经常断连"
        }, ensure_ascii=False, indent=2)
    
    elif "生成改进建议" in prompt:
        return """
改进建议：

1. 技术改进：
   - 升级蓝牙芯片至最新5.3版本，提升抗干扰能力
   - 优化天线设计，增强信号穿透力

2. 产品定位：
   - 考虑推出"通勤版"，针对复杂环境优化
   - 提供30天无理由退换，降低用户决策成本

3. 售后服务：
   - 建立连接问题快速响应通道
   - 提供固件升级服务改善稳定性

4. 价格策略：
   - 可考虑推出标准版和专业版两个价位
   - 标准版优化性价比，吸引价格敏感用户
"""
    
    return "模拟响应"


# ============================================
# 提示词链实现
# ============================================

class PromptChain:
    """提示词链处理器"""
    
    def __init__(self):
        self.history = []  # 记录每一步的处理历史
    
    def step_1_extract_info(self, review_text: str) -> Dict[str, Any]:
        """
        步骤1：从评论中提取关键信息
        """
        print("\n" + "="*60)
        print("【步骤 1】提取关键信息")
        print("="*60)
        
        prompt = f"""
请从以下产品评论中提取关键信息：

评论内容：
{review_text}

请提取以下信息并以 JSON 格式返回：
- 产品类型
- 优点（列表）
- 缺点（列表）
- 用户需求
"""
        
        print(f"[提示词]：\n{prompt}\n")
        
        # 调用 LLM
        response = simulate_llm_call(prompt, review_text)
        print(f"[输出]：\n{response}\n")
        
        # 保存历史
        self.history.append({
            "step": 1,
            "name": "提取关键信息",
            "input": review_text,
            "output": response
        })
        
        return json.loads(response)
    
    def step_2_analyze_sentiment(self, extracted_info: Dict[str, Any]) -> Dict[str, Any]:
        """
        步骤2：分析情感和问题点
        使用步骤1的输出作为输入
        """
        print("\n" + "="*60)
        print("【步骤 2】分析情感和问题点")
        print("="*60)
        
        context = json.dumps(extracted_info, ensure_ascii=False, indent=2)
        
        prompt = f"""
基于以下提取的信息，请分析情感和问题点：

提取的信息：
{context}

请分析并以 JSON 格式返回：
- 整体情感（正面/中性/负面）
- 满意度评分（1-10）
- 主要问题
- 关键痛点
"""
        
        print(f"[提示词]：\n{prompt}\n")
        
        # 调用 LLM（注意这里使用了上一步的输出）
        response = simulate_llm_call(prompt, context)
        print(f"[输出]：\n{response}\n")
        
        # 保存历史
        self.history.append({
            "step": 2,
            "name": "分析情感",
            "input": extracted_info,
            "output": response
        })
        
        return json.loads(response)
    
    def step_3_generate_recommendations(self, 
                                       extracted_info: Dict[str, Any],
                                       sentiment_analysis: Dict[str, Any]) -> str:
        """
        步骤3：生成改进建议
        综合使用前面两步的输出
        """
        print("\n" + "="*60)
        print("【步骤 3】生成改进建议")
        print("="*60)
        
        context = f"""
关键信息：
{json.dumps(extracted_info, ensure_ascii=False, indent=2)}

情感分析：
{json.dumps(sentiment_analysis, ensure_ascii=False, indent=2)}
"""
        
        prompt = f"""
基于以下分析结果，请生成具体的产品改进建议：

{context}

请生成：
1. 技术改进方案
2. 产品定位调整
3. 售后服务优化
4. 价格策略建议
"""
        
        print(f"[提示词]：\n{prompt}\n")
        
        # 调用 LLM（综合使用前面所有步骤的输出）
        response = simulate_llm_call(prompt, context)
        print(f"[输出]：\n{response}\n")
        
        # 保存历史
        self.history.append({
            "step": 3,
            "name": "生成建议",
            "input": {"extracted_info": extracted_info, "sentiment": sentiment_analysis},
            "output": response
        })
        
        return response
    
    def run(self, review_text: str) -> Dict[str, Any]:
        """
        运行完整的提示词链
        """
        print("\n" + "="*60)
        print("开始执行提示词链")
        print("="*60)
        
        # 步骤1：提取信息
        extracted_info = self.step_1_extract_info(review_text)
        
        # 步骤2：分析情感（使用步骤1的输出）
        sentiment_analysis = self.step_2_analyze_sentiment(extracted_info)
        
        # 步骤3：生成建议（使用步骤1和2的输出）
        recommendations = self.step_3_generate_recommendations(
            extracted_info, 
            sentiment_analysis
        )
        
        print("\n" + "="*60)
        print("提示词链执行完成")
        print("="*60)
        
        return {
            "extracted_info": extracted_info,
            "sentiment_analysis": sentiment_analysis,
            "recommendations": recommendations,
            "history": self.history
        }


# ============================================
# 对比：单一提示词 vs 提示词链
# ============================================

def single_prompt_approach(review_text: str):
    """
    单一提示词方法（对比用）
    问题：任务太复杂，容易遗漏信息，难以控制输出格式
    """
    print("\n" + "="*60)
    print("【对比】使用单一提示词处理（不推荐）")
    print("="*60 + "\n")
    
    complex_prompt = f"""
请分析以下产品评论，并完成所有这些任务：
1. 提取产品类型、优点、缺点、用户需求
2. 分析情感倾向和满意度
3. 识别关键痛点
4. 生成改进建议（包括技术、定位、服务、价格策略）

评论内容：
{review_text}

请以结构化方式返回所有结果。
"""
    
    print(f"[复杂提示词]：\n{complex_prompt}\n")
    print("[-] 问题：")
    print("  - 任务过于复杂，LLM 容易遗漏部分要求")
    print("  - 输出格式难以控制")
    print("  - 无法插入中间处理逻辑")
    print("  - 调试困难，出错时难以定位问题")
    print("  - 无法复用单个步骤\n")


# ============================================
# 主程序
# ============================================

def main():
    """主函数：演示提示词链的使用"""
    
    # 示例评论
    review_text = """
    这款无线耳机音质确实不错，听歌时能感受到很好的细节。
    佩戴也很舒适，长时间使用耳朵不会疼。续航能力也挺强的，
    充一次电可以用好几天。
    
    但是有个比较大的问题，就是连接稳定性不太好。在地铁上或者
    人多的地方经常会断连，需要重新配对，这点比较影响体验。
    另外价格也有点贵，如果能便宜一些就更好了。
    
    我主要是通勤时用，希望能有稳定的连接。
    """
    
    print("\n" + "="*60)
    print("原始评论：")
    print("="*60)
    print(review_text)
    
    # 对比：单一提示词方法
    single_prompt_approach(review_text)
    
    # 提示词链方法
    chain = PromptChain()
    result = chain.run(review_text)
    
    # 总结
    print("\n" + "="*60)
    print("提示词链的优势总结")
    print("="*60)
    print("""
1. [+] 任务分解：每一步只关注一个具体目标，降低复杂度
2. [+] 可控性强：可以精确控制每一步的输入输出格式
3. [+] 易于调试：出问题时可以快速定位是哪一步出错
4. [+] 可复用：每个步骤可以独立测试和复用
5. [+] 可扩展：容易添加新步骤或修改现有步骤
6. [+] 可观测：可以查看每一步的中间结果
7. [+] 集成外部工具：可以在步骤间插入 API 调用、数据库查询等
    """)
    
    print("\n" + "="*60)
    print("实际应用场景")
    print("="*60)
    print("""
- 文档处理：提取 → 总结 → 分类 → 生成报告
- 代码审查：解析 → 检测问题 → 评估严重性 → 生成建议
- 客服系统：理解问题 → 检索知识库 → 生成回答 → 优化语气
- 内容创作：大纲 → 分段写作 → 润色 → SEO 优化
- 数据分析：清洗 → 统计 → 可视化建议 → 洞察总结
    """)


if __name__ == "__main__":
    main()


# ============================================
# 进阶：集成真实 LLM API 的示例代码
# ============================================

"""
# 使用 OpenAI API 的真实实现示例：

import openai
import os

def real_llm_call(prompt: str, model: str = "gpt-4") -> str:
    '''真实的 LLM 调用'''
    client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
    
    response = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": "你是一个专业的产品分析助手。"},
            {"role": "user", "content": prompt}
        ],
        temperature=0.7
    )
    
    return response.choices[0].message.content

# 只需将 simulate_llm_call 替换为 real_llm_call 即可


# 使用 LangChain 的实现示例：

from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain
from langchain_openai import ChatOpenAI

def langchain_prompt_chain():
    '''使用 LangChain 实现提示词链'''
    llm = ChatOpenAI(model="gpt-4", temperature=0.7)
    
    # 步骤1：提取
    extract_prompt = PromptTemplate(
        input_variables=["review"],
        template="从以下评论中提取关键信息：\n{review}"
    )
    extract_chain = LLMChain(llm=llm, prompt=extract_prompt)
    
    # 步骤2：分析
    analyze_prompt = PromptTemplate(
        input_variables=["extracted_info"],
        template="分析以下信息的情感：\n{extracted_info}"
    )
    analyze_chain = LLMChain(llm=llm, prompt=analyze_prompt)
    
    # 链接执行
    extracted = extract_chain.run(review="...")
    analyzed = analyze_chain.run(extracted_info=extracted)
    
    return analyzed
"""

